package cn.dvptech.remotecontrol.ui.activity

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.res.Configuration
import android.graphics.Path
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.IBinder
import android.os.Vibrator
import android.view.KeyEvent
import android.view.View
import android.view.accessibility.AccessibilityEvent
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.recyclerview.widget.RecyclerView
import cn.bingoogolapple.qrcode.core.QRCodeView
import cn.bingoogolapple.qrcode.zxing.ZXingView
import cn.dvptech.remotecontrol.R
import cn.dvptech.remotecontrol.aop.Log
import cn.dvptech.remotecontrol.app.AppActivity
import cn.dvptech.remotecontrol.assists.Assists
import cn.dvptech.remotecontrol.assists.AssistsServiceListener
import cn.dvptech.remotecontrol.screenmirror.ScreenRecorderService
import cn.dvptech.remotecontrol.screenmirror.configuration.VideoConfiguration
import cn.dvptech.remotecontrol.screenmirror.sender.OnSenderListener
import cn.dvptech.remotecontrol.ui.adapter.DeviceAdapter
import cn.dvptech.remotecontrol.ui.dialog.MessageDialog
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.hjq.base.BaseAdapter
import com.hjq.base.BaseDialog
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.hjq.widget.layout.WrapRecyclerView
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber


class MainActivity : AppActivity(), OnRefreshLoadMoreListener, BaseAdapter.OnItemClickListener,
    OnSenderListener, QRCodeView.Delegate, AssistsServiceListener {

    override fun getLayoutId(): Int = R.layout.main_activity

    private val refreshLayout: SmartRefreshLayout? by lazy { findViewById(R.id.main_rl_status_refresh) }
    private val recyclerView: WrapRecyclerView? by lazy { findViewById(R.id.main_rv_status_list) }
    private val closeCurrentConnect: AppCompatButton? by lazy { findViewById(R.id.main_close_connection) }
    private val btnOpenFZService: AppCompatButton? by lazy { findViewById(R.id.main_open_fz_service) }

    private var adapter: DeviceAdapter? = null

    private var serverIP: String? = null

    // 投屏service
    private var mMediaProjectionManager: MediaProjectionManager? = null
    private var isRecord = false

    private var screenRecorderService: ScreenRecorderService? = null
    private var intentActivityResultLauncher: ActivityResultLauncher<Intent>? = null

    private val scanQrcodeView: ZXingView? by lazy { findViewById(R.id.scanQrcodeView) }

    var currentOrientation: Int = Configuration.ORIENTATION_UNDEFINED

    private fun requestRecording() {
        if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
            toast("此设备不支持录制屏幕")
            return
        }
        mMediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        intentActivityResultLauncher!!.launch(mMediaProjectionManager!!.createScreenCaptureIntent())
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        super.onAccessibilityEvent(event)
        event.let {
            if (it.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED ||
                it.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
            ) {
                val orientation = Assists.service?.resources?.configuration?.orientation ?: Configuration.ORIENTATION_PORTRAIT
                if (currentOrientation == orientation) {
                    return@let
                }
                currentOrientation = orientation
                val width = ScreenUtils.getScreenWidth()
                val height = ScreenUtils.getScreenHeight()
                android.util.Log.d("123456", "Screen is in Landscape mode: width=$width/height=$height")
                GlobalScope.launch(Dispatchers.IO) {
                    //响应当前设备宽高
                    screenRecorderService?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                        put("type", "GET_SCREEN_RESPONSE")
                        put("data", hashMapOf<String, Any>().apply {
                            put("screenWidth", width)
                            put("screenHeight", height)
                        })
                        put("orientation", currentOrientation)
                    }))
                }
            }
        }
    }

    override fun initView() {
        Assists.serviceListeners.add(this)
        val intent = Intent(this, ScreenRecorderService::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent);
        } else {
            startService(intent);
        }
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        scanQrcodeView?.setDelegate(this)

        setOnClickListener(closeCurrentConnect, btnOpenFZService)
        showSettingService()

        adapter = DeviceAdapter(this)
        adapter?.setOnItemClickListener(this)
        recyclerView?.adapter = adapter

        refreshLayout?.setOnRefreshLoadMoreListener(this)

        intentActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.data != null && result.resultCode == RESULT_OK) {
                Timber.i("onActivityResult: ${result.resultCode}")
                requestRecordSuccess(result.resultCode, result.data!!)
            } else {
                toast("投屏失败")
                requestRecordFail()
            }
        }
    }

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            screenRecorderService = (p1 as ScreenRecorderService.ScreenBinder).getService()
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
            screenRecorderService = null
        }
    }


    /**
     * 开启无障碍 辅助服务设置
     */
    private fun showSettingService() {
        if (Assists.service != null) return

        MessageDialog.Builder(this)
            .setTitle(R.string.common_permission_alert)
            .setMessage("请开启无障碍->辅助服务,找到本App名字，点击开启")
            .setConfirm("去授权")
            .setCancel("取消")
            .setCancelable(false)
            .setListener(object : MessageDialog.OnListener {
                override fun onConfirm(dialog: BaseDialog?) {
                    Assists.openAccessibilitySetting()
                }
            })
            .show()
    }

    override fun initData() {

    }

    override fun onClick(view: View) {
        when (view) {
            btnOpenFZService -> {
                if (!Assists.isAccessibilityServiceEnabled()) {
                    Assists.openAccessibilitySetting()
                } else {
                    // 已开启服务
                    toast(R.string.wifi_p2p_opened_assists_service)
                }
            }

            closeCurrentConnect -> {
                if (isRecord) {
                    MessageDialog.Builder(this@MainActivity)
                        .setTitle("关闭提示")
                        .setMessage("确定要关闭投屏吗？")
                        .setConfirm(getString(R.string.common_confirm))
                        .setCancel(getString(R.string.common_cancel))
                        .setListener(object : MessageDialog.OnListener {
                            override fun onConfirm(dialog: BaseDialog?) {
                                screenRecorderService?.stopRecording()
                                isRecord = false
                                closeCurrentConnect?.text = "扫一扫投屏"
                            }
                        })
                        .show()
                } else {
                    Assists.service ?: let {
                        ToastUtils.showShort("请先开启辅助服务")
                        return
                    }
                    scanQrcodeView?.visibility = View.VISIBLE
                    // 扫描
                    scanQrcodeView?.startCamera()
                    scanQrcodeView?.startSpotAndShowRect()
                }
            }
        }
    }

    override fun onRefresh(p0: RefreshLayout) {
        toast("正在刷新")
        postDelayed({
            adapter?.clearData()
            this.refreshLayout?.finishRefresh()
        }, 1000)
    }

    override fun onLoadMore(p0: RefreshLayout) {
        toast("没有了")
    }

    override fun onItemClick(recyclerView: RecyclerView?, itemView: View?, position: Int) {
        toast("onItemClick:" + adapter?.getItem(position)?.deviceName)
        ThreadUtils.runOnUiThread {
            /** 点击连接 某一个设备*/

        }
    }

    override fun onDestroy() {
        screenRecorderService?.stopRecording()
        scanQrcodeView?.onDestroy()
        super.onDestroy()
        Assists.serviceListeners.remove(this)
    }

    override fun onResume() {
        super.onResume()
        if (Assists.isAccessibilityServiceEnabled()) {
            //开启辅助服务
            btnOpenFZService?.text = getString(R.string.wifi_p2p_opened_assists_service)
        } else {
            //辅助服务已开启
            btnOpenFZService?.text = getString(R.string.wifi_p2p_open_assists_service)
        }
        checkPermissions()
        screenRecorderService?.resumeRecording()
    }

    override fun isStatusBarEnabled(): Boolean {
        // 使用沉浸式状态栏
        return !super.isStatusBarEnabled()
    }

    private fun checkPermissions() {
        XXPermissions.with(this)
            .permission(Permission.ACCESS_FINE_LOCATION)
            .permission(Permission.WRITE_EXTERNAL_STORAGE)
            .permission(Permission.READ_EXTERNAL_STORAGE)
            .permission(Permission.CAMERA)
            .permission(Permission.RECORD_AUDIO)
            .request(object : OnPermissionCallback {

                override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                    if (!allGranted) {
                        toast("获取部分权限成功，但部分权限未正常授予")
                        return
                    }

                }

                override fun onDenied(
                    permissions: MutableList<String>,
                    doNotAskAgain: Boolean
                ) {
                    if (doNotAskAgain) {
                        toast("被永久拒绝授权，请手动授予权限")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(this@MainActivity, permissions)
                    } else {
                        toast("获取权限失败")
                    }
                }
            })
    }

    override fun onPause() {
        super.onPause()
    }

    /**
     * 开启投屏
     */
    private fun requestRecordSuccess(resultCode: Int, resultData: Intent) {
        isRecord = true
        screenRecorderService?.startScreenCapture(mMediaProjectionManager!!, resultCode, resultData, serverIP!!, this)
    }

    private fun requestRecordFail() {
        Timber.d("requestRecordFail...")
    }

    override fun onConnecting() {
        Timber.d("onConnecting...")
    }

    override fun onConnected() {
        Timber.d("onConnected...")
    }

    override fun onDisConnected() {
        Timber.d("onDisConnected...")
        screenRecorderService?.stopRecording()
        isRecord = false
        closeCurrentConnect?.text = "扫一扫投屏"
    }

    override fun onPublishFail() {
        Timber.d("onPublishFail...")
    }

    override fun onNetGood() {
    }

    override fun onNetBad() {
    }

    override fun onReceiveMessage(message: String?) {
        Timber.d("message $message")
        handleMessage(message!!)
    }

    override fun shutDown() {

    }

    companion object {


        // 投屏service
        private var mMediaProjectionManager: MediaProjectionManager? = null

        @Log
        fun start(context: Context) {
            val intent = Intent(context, MainActivity::class.java)
            if (context !is Activity) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            context.startActivity(intent)
        }
    }

    /**
     * 控制消息处理
     */
    @Throws(JSONException::class)
    private fun handleMessage(message: String) {
        val jsonObject = JSONObject(message)
        val type = jsonObject.optString("type")

        //获取屏幕数据
        when (type) {
            "GET_SCREEN" -> {
                //响应当前设备宽高
                screenRecorderService?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                    put("type", "GET_SCREEN_RESPONSE")
                    put("data", hashMapOf<String, Any>().apply {
//                        put("screenWidth", VideoConfiguration.ADVANCED_WIDTH)
//                        put("screenHeight", VideoConfiguration.ADVANCED_HEIGHT)
                        put("screenWidth", ScreenUtils.getScreenWidth())
                        put("screenHeight", ScreenUtils.getScreenHeight())
                    })
                    put("orientation", Assists.service?.resources?.configuration?.orientation ?: Configuration.ORIENTATION_PORTRAIT)

                }))
            }
            //屏幕控制
            "CONTROL" -> {
                val data = jsonObject.optJSONObject("data") ?: return
                //路径数据
                val paths = data.optJSONArray("paths") ?: return
                val path = Path()
                //遍历构建手势路径
                for (i in 0 until paths.length()) {
                    val point = paths.optJSONObject(i)
                    val x = point.optInt("x")
                    val y = point.optInt("y")
                    if (i == 0) {
                        path.moveTo(x.toFloat(), y.toFloat())
                    } else {
                        path.lineTo(x.toFloat(), y.toFloat())
                    }
                }
                //手势执行时长
                val duration = data.optLong("duration")
                //执行控制手势，10为延迟时间
                Assists.gesture(path, 10, duration)
            }

            "BACK" -> {
                //返回
                Assists.back()
            }

            "HOME" -> {
                //回到主页
                Assists.home()
            }

            "TASKS" -> {
                //最近任务
                Assists.tasks()
            }

            "NOTIFICATIONS" -> {
                //通知栏
                Assists.notifications()
            }
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            this.moveTaskToBack(true)
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun vibrate() {
        val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
        vibrator.vibrate(200)
    }

    override fun onScanQRCodeSuccess(result: String?) {
        Timber.d("扫描结果为：$result")
        vibrate()
        if (!StringUtils.isEmpty(result)) {
            serverIP = result
            //开启投屏
            requestRecording()
            scanQrcodeView?.stopCamera()
            scanQrcodeView?.visibility = View.GONE
            closeCurrentConnect?.text = "关闭投屏"
        } else {
            scanQrcodeView?.startSpot()
        }
    }

    override fun onCameraAmbientBrightnessChanged(isDark: Boolean) {
        // 这里是通过修改提示文案来展示环境是否过暗的状态，接入方也可以根据 isDark 的值来实现其他交互效果
    }

    override fun onScanQRCodeOpenCameraError() {
        Timber.d("打开相机出错")
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

    }
}
